<?php

namespace Yolo\Service;

use Yac;
use Yolo\Utils\System;
use function Hyperf\Support\make;

/**
 * Singleton
 * @author lushaoming<lushaoming6@gmail.com>
 * @date 2024/2/20
 */
class Singleton
{
    private static array $instances = [];

    private static array $instancesTags = [];

    private static ?Yac $yac = null;

    /**
     * @param string $name
     * @param array $parameters
     * @return mixed|object|null
     */
    public static function make(string $name, array $parameters = []): mixed
    {
        if (System::getWorkerNum() === 1) {

            if (!isset(self::$instances[$name])) {
                self::$instances[$name] = make($name, $parameters);
                if (method_exists(self::$instances[$name], 'initializer')) {
                    (self::$instances[$name])->initializer();
                }
            }

            return self::$instances[$name];
        }

        self::initYac();

        $tag = self::$yac->get('tag:' . $name);
        // 如果yac里的tag与$instancesTags的tag一致，说明实例未改变，则可以直接返回
        if ($tag && isset(self::$instancesTags[$name]) && $tag === self::$instancesTags[$name]) {
            return self::$instances[$name];
        }

        $instance = self::$yac->get($name);
        if (!$instance) {
            $tag = ''; // 不存在实例，则置空tag
            $instance = make($name, $parameters);
            if (method_exists($instance, 'initializer')) {
                $instance->initializer();
            }

            self::$yac->set($name, $instance);
        }

        if (!$tag) {
            $tag = microtime();
            self::$yac->set('tag:' . $name, $tag);
        }

        self::$instancesTags[$name] = $tag;
        self::$instances[$name] = $instance;

        return $instance;
    }

    private static function initYac(): void
    {
        if (is_null(self::$yac)) {
            self::$yac = new Yac();
        }
    }
}
